Skip to content

[EuiStepsHorizontal][A11y] Prevent screen reader duplication#9574

Merged
mgadewoll merged 7 commits intoelastic:mainfrom
mgadewoll:stepshorizontal/a11y-prevent-duplication
Apr 24, 2026
Merged

[EuiStepsHorizontal][A11y] Prevent screen reader duplication#9574
mgadewoll merged 7 commits intoelastic:mainfrom
mgadewoll:stepshorizontal/a11y-prevent-duplication

Conversation

@mgadewoll
Copy link
Copy Markdown
Contributor

@mgadewoll mgadewoll commented Apr 8, 2026

Summary

This PR updates EuiStepsHorizontal to fix duplicate output for screen readers.
The output for screen readers previously read:

  • title attribute (though this is not consistently read across screen readers)
  • DOM content
    • visible label
    • hidden screen reader text OR icon label (same as title)

Instead of using the title attribute we can use aria-label instead which results in only the aria-label being read for the button element.

⚠️ This means we won't have the browser "tooltip" on hover but considering the cons/pros of that attribute and that we're generally considering to remove it across EUI, this should be reasonable to do. The steps themselves provide all information, the title isn't actually adding further benefit.

API Changes

🟢 No API changes

Screenshots

screen reader output

screen reader Before After
NVDA / Chrome Screenshot 2026-04-08 at 12 10 15 Screenshot 2026-04-08 at 12 09 43
JAWS / Chrome Screenshot 2026-04-08 at 12 05 03 Screenshot 2026-04-08 at 12 07 00

video

screen reader Before After
NVDA / Chrome
Screen.Recording.2026-04-08.at.12.09.49.mov
Screen.Recording.2026-04-08.at.12.09.23.mov
JAWS / Chrome
Screen.Recording.2026-04-08.at.12.04.24.mov
Screen.Recording.2026-04-08.at.12.06.28.mov
VoiceOver / Safari
Screen.Recording.2026-04-08.at.12.19.22.mov
Screen.Recording.2026-04-08.at.12.18.55.mov

Impact Assessment

Note: Most PRs should be tested in Kibana to help gauge their Impact before merging.

  • 🔴 Breaking changes — What will break? How many usages in Kibana/Cloud UI are impacted?
  • 💅 Visual changes — May impact style overrides; could require visual testing. Explain and estimate impact.
  • 🧪 Test impact — May break functional or snapshot tests (e.g., HTML structure, class names, default values).
  • 🔧 Hard to integrate — If changes require substantial updates to Kibana, please stage the changes and link them here.

Impact level: 🟢 Low - Due to DOM changes, snapshots might need updating.

Release Readiness

  • Documentation: {link to docs page(s)}
  • Figma: {link to Figma or issue}
  • Migration guide: {steps or link, for breaking/visual changes or deprecations}
  • Adoption plan (new features): {link to issue/doc or outline who will integrate this and where}

QA instructions for reviewer

  • verify that navigating the component in screen readers (JAWS, NVDA, VO) doesn't result in duplication anymore
  • verify there is no unexpected visual/functional regression with production

Checklist before marking Ready for Review

Reviewer checklist

  • Approved Impact Assessment — Acceptable to merge given the consumer impact.
  • Approved Release Readiness — Docs, Figma, and migration info are sufficient to ship.

@mgadewoll mgadewoll self-assigned this Apr 8, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves EuiStepsHorizontal / EuiStepHorizontal screen reader output by replacing the title attribute with aria-label to prevent duplicate announcements.

Changes:

  • Replaced the title attribute on EuiStepHorizontal’s <button> with aria-label.
  • Updated Jest snapshots to reflect the new attribute output.
  • Added an upcoming changelog entry documenting the accessibility fix.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
packages/eui/src/components/steps/step_horizontal.tsx Switches from title to aria-label on the step button to prevent duplicate SR output
packages/eui/src/components/steps/snapshots/steps_horizontal.test.tsx.snap Snapshot updates for EuiStepsHorizontal button attributes
packages/eui/src/components/steps/snapshots/step_horizontal.test.tsx.snap Snapshot updates for EuiStepHorizontal button attributes
packages/eui/changelogs/upcoming/9574.md Changelog entry for the accessibility improvement

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/eui/src/components/steps/step_horizontal.tsx Outdated
Comment on lines 119 to 123
aria-disabled={status === 'disabled' ? true : undefined}
className={classes}
title={titleAttr}
aria-label={titleAttr}
onClick={onStepClick}
disabled={disabled}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aria-disabled is set based on status === 'disabled', but the actual disabled behavior is controlled only by the disabled prop (disabled={disabled} and onStepClick only guards on disabled). This allows a status="disabled" step to still be clickable/activatable despite being announced as disabled. Consider using a single computed boolean (e.g., isDisabled = disabled || status === 'disabled') for aria-disabled, the disabled attribute, and the click guard so behavior matches the a11y state.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not due to the changes in this PR. There might be benefit to having the button focusable if disabled, so I wouldn't change the aria-disabled vs disabled behavior here at this point. What we can do though is guard the onClick on both to prevent it from being being fired if only status === 'disabled' is passed without disabled.

Updated in 0fa990a

@weronikaolejniczak weronikaolejniczak self-requested a review April 13, 2026 08:30
Copy link
Copy Markdown
Contributor

@weronikaolejniczak weronikaolejniczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with NVDA/Chrome, JAWS/Chrome and VO/Safari. There's no duplication ✅

2 doubts (one in a separate comment):

❓ I'm all for removing the title attr but I'm wondering if we should replace it with an EuiToolTip or not... What do you think?

Comment thread packages/eui/src/components/steps/step_horizontal.tsx
@mgadewoll
Copy link
Copy Markdown
Contributor Author

❓ I'm all for removing the title attr but I'm wondering if we should replace it with an EuiToolTip or not... What do you think?

@weronikaolejniczak I'm not sure if it has too much value. 🤔 Yes, the title was a text representation of the steps but it didn't have any other function (no alternative for truncation etc). The text alternative for assistive technologies is the aria-label now.
I'm leaning towards "no" here as the title was mouse only anyway. If we add a tooltip it's actually changing the behavior more because we're adding it for keyboard as well. Imho, it would rather be a new feature then, which we could add if the need arises.

Copy link
Copy Markdown
Contributor

@weronikaolejniczak weronikaolejniczak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing my doubts, Lene! I agree the tooltip would be an enhancement, let's leave it for now. And thanks for updating the changelog!

🟢

@elasticmachine
Copy link
Copy Markdown
Collaborator

💚 Build Succeeded

History

cc @mgadewoll

@elasticmachine
Copy link
Copy Markdown
Collaborator

💚 Build Succeeded

History

cc @mgadewoll

@mgadewoll mgadewoll merged commit 94a166c into elastic:main Apr 24, 2026
5 checks passed
@mgadewoll mgadewoll deleted the stepshorizontal/a11y-prevent-duplication branch April 24, 2026 09:54
acstll added a commit to elastic/kibana that referenced this pull request Apr 28, 2026
## Dependency updates

- `@elastic/eui` - v114.2.0 ⏩ v114.3.0

---

## Package updates

## [`v114.3.0`](https://github.com/elastic/eui/releases/v114.3.0)

- Updated `productDashboard` icon.
([#9607](elastic/eui#9607))
- Updated `EuiStepsHorizontal` to prevent steps being clickable when
`status="disabled"` ([#9574](elastic/eui#9574))

**Bug fixes**

- Fixed broken SVG for `chartPie` icon.
([#9607](elastic/eui#9607))
- Fixed a bug in `EuiDataGrid` that caused the scroll position to reset
when using middle mouse button to scroll the container.
([#9613](elastic/eui#9613))
- Fixed `EuiFlyout` to compare `pushMinBreakpoint` against the
container's width, instead of the viewport width, when the `container`
prop is provided. This ensures app-scoped flyouts switch between push
and overlay modes based on the space actually available inside their
container. ([#9592](elastic/eui#9592))

**Accessibility**

- Fixed duplicate screen reader output for `EuiStepsHorizontal`
([#9574](elastic/eui#9574))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants